package edu.towson.cosc.cosc455.cbrown.mdcomp;

import edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer;
import java.util.ArrayList;

public class MySynAnalyzer implements SyntaxAnalyzer {
	MyLexAnalyzer lex = new MyLexAnalyzer();
	public static ArrayList<String> ptree = new ArrayList<String>();

	//Start State. Grammar for the entire document.
	public void document() throws CompilerException {
		
		if (!MyCompiler.token.equalsIgnoreCase("#Start Document")) {
			String message = "A #Start Document annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else {
			ptree.add(MyCompiler.token);
		
			 
			lex.getNextToken();
			define();
		
			head();
		
			body();
		
			if (!MyCompiler.token.equalsIgnoreCase("#End Document")) {
				String message = "An #End Document annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
		
			else {
				ptree.add(MyCompiler.token);
		
				lex.getNextToken();
		
				if(MyCompiler.token != null) {
					String message = "Nothing  was expected after the #End Document annotation and " + MyCompiler.token + "  was found.";
					throw new CompilerException(message);
				}
			}
		
		//ELSE calls semantic
		}
	}
		

	//Grammar for Head Tag
	public void head() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Head")) {
			ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			title();
			
			if (!MyCompiler.token.equalsIgnoreCase("#End Head")) {
				String message = "A #End Head annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			
		}
	}

	//Grammar for Title tag
	public void title() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Title")) {
			ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			text();
			
			if (!MyCompiler.token.equalsIgnoreCase("#End Title")) {
				String message = "A #End Title annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			
		}
	}
	
	//Grammar for Body tag
	public void body() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Paragraph")) {
			paragraph();
			
			body();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start Bold")) {
			bold();
			
			body();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start Italics")) {
			italics();
			
			body();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start List")) {
			list();
			
			body();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start Use") || !MyCompiler.token.startsWith("#")) {
			innerText();
			
			body();
		}
	}
	
	//Grammar for Paragraph tag
	public void paragraph() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Paragraph")) {
			ptree.add(MyCompiler.token);
			lex.getNextToken();
			
			define();
		
			innerParagraph();
			
			if (!MyCompiler.token.equalsIgnoreCase("#End Paragraph")) {
				String message = "A #End Paragraph annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			
		}
	}
	
	//Grammar for InnerParagraph, used for anything in a paragraph after the Define tag
	public void innerParagraph() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Bold")) {
			bold();
			
			innerParagraph();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start Italics")) {
			italics();
			
			innerParagraph();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start List")) {
			list();
		
			innerParagraph();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Newline")) {
			ptree.add(MyCompiler.token);
			lex.getNextToken();
			innerParagraph();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start Use") || !MyCompiler.token.startsWith("#")){
			innerText();

			innerParagraph();
		}
	}
	
	//Grammar for InnerText used for anything in Text after define
	public void innerText() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Use")) {
			use();
			
			innerText();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Newline")) {
			ptree.add(MyCompiler.token);
			lex.getNextToken();
			innerText();
		}
		
		if (!MyCompiler.token.startsWith("#")) {
			text();
			
			innerText();
		}
	}
	
	//Grammar for Bold tag
	public void bold() throws CompilerException {
		if (!MyCompiler.token.equalsIgnoreCase("#Start Bold")) {
			String message = "A #Start Bold annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else {
			ptree.add(MyCompiler.token);
		
			lex.getNextToken();
			define();
		
			innerText();
			
			if (!MyCompiler.token.equalsIgnoreCase("#End Bold")) {
				String message = "A #End Bold annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
		
			else
				ptree.add(MyCompiler.token);
		
			lex.getNextToken();
		}
	}

	//Grammar for Italics tag
	public void italics() throws CompilerException {
		if (!MyCompiler.token.equalsIgnoreCase("#Start Italics")) {
			String message = "A #Start Italics annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
		define();
		
		innerText();
			
		lex.getNextToken();
		if (!MyCompiler.token.equalsIgnoreCase("#End Italics")) {
			String message = "A #End Italics annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
	}

	//Grammar for List tag
	public void list() throws CompilerException {
		if (!MyCompiler.token.equalsIgnoreCase("#Start List")) {
			String message = "A #Start List annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
		if (!MyCompiler.token.equalsIgnoreCase("#Start Item")) {
			String message = "A #Start Item annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
		define();
		
		innerList();
		
		if (!MyCompiler.token.equalsIgnoreCase("#End Item")) {
			String message = "A #End Item annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
		item();
			
		if (!MyCompiler.token.equalsIgnoreCase("#End List")) {
			String message = "A #End List annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
	}

	//Grammar for items in a list
	public void item() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Item")) {
			ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			define();
			
			innerList();

			if (!MyCompiler.token.equalsIgnoreCase("#End Item")) {
				String message = "A #End Item annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			item();
		}
	}
	
	//Grammar for InnerList, anything in a list after define
	public void innerList() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Bold")) {
			bold();

			innerList();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start Italics")) {
			italics();

			innerList();
		}
		
		if (MyCompiler.token.equalsIgnoreCase("#Start List")) {
			list();
			
			innerList();
		}

		if (MyCompiler.token.equalsIgnoreCase("#Start Use") || !MyCompiler.token.startsWith("#")){
			innerText();

			innerList();
		}
	}

	//Grammar for Audio tag
	public void audio() throws CompilerException {
		if (!MyCompiler.token.equalsIgnoreCase("#Start Audio")) {
			String message = "A #Start Audio annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
		text();
		
		if (!MyCompiler.token.equalsIgnoreCase("#End Audio")) {
			String message = "An #End Audio annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		lex.getNextToken();
	}

	//Grammar for Video tag
	public void video() throws CompilerException {
		if (!MyCompiler.token.equalsIgnoreCase("#Start Video")) {
			String message = "A #Start Video annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		
		lex.getNextToken();
		text();
		
		if (!MyCompiler.token.equalsIgnoreCase("#End Video")) {
			String message = "An #End Video annotation  was expected when a " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
		
		else
			ptree.add(MyCompiler.token);
		lex.getNextToken();
	}
	
	//All text
	public void text() throws CompilerException {
		if (!MyCompiler.token.startsWith("#")) {
			ptree.add(MyCompiler.token);
			lex.getNextToken();
		}
		
		else {
			String message = "Text  was expected when " + MyCompiler.token + " was found.";
			throw new CompilerException(message);
		}
	}


	//Grammar for Variable Define tag
	public void define() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Define")) {
			ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			if(!MyCompiler.token.equalsIgnoreCase("#Name")) {
				String message = "A #Name annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
		
			lex.getNextToken();
			text();
			
			if (!MyCompiler.token.equalsIgnoreCase("#Value")) {
				String message = "A #Value annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			text();
			
			if (!MyCompiler.token.equalsIgnoreCase("#End Define")) {
				String message = "A #End Define annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			define();
		}
	}


	//Grammar for Use Variable tag
	public void use() throws CompilerException {
		if (MyCompiler.token.equalsIgnoreCase("#Start Use")) {
			ptree.add(MyCompiler.token);
			
			lex.getNextToken();
			text();
			
			if (!MyCompiler.token.equalsIgnoreCase("#End Use")) {
				String message = "A #End Use annotation  was expected when a " + MyCompiler.token + " was found.";
				throw new CompilerException(message);
			}
			
			else
				ptree.add(MyCompiler.token);
			lex.getNextToken();
		}
	}

}
